'''
Created on May 7, 2011

Test module for models/views

@author: glow
'''

import unittest

from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.ext import testbed
from google.appengine.api import users

from controlledterminology.models import NCI_Controlled_Terminology_CodeListItem, CodedTerminology, \
                                          NCI_Controlled_Terminology_Codelist, Organisation, Controlled_Terminology_Source

from models import Attribute, Instance, Template, Template_Variable, Collection, CollectionAttribute, \
                  CollectionAttributeTemplate, CollectionType, Concept, Context                  

#
# Test Superclass
# 

class framework_Test(unittest.TestCase):

  def setUp(self):
    """
    From: http://code.google.com/appengine/docs/python/tools/localunittesting.html
    """
    # First, create an instance of the Testbed class.
    self.testbed = testbed.Testbed()
    # Then activate the testbed, which prepares the service stubs for use.
    self.testbed.activate()
    # Next, declare which service stubs you want to use.
    self.testbed.init_datastore_v3_stub()
    self.testbed.init_memcache_stub()
    self.testbed.init_user_stub()

  def tearDown(self):
    self.testbed.deactivate()


class Test_Context(framework_Test):
  
  def test_Create_Context(self):
    ctx = Context(name='Some Name', label='Some label', description='Some description')
    ctx.put()
    self.assertEqual(1, len(Context.all().fetch(2)))
    
  def test_Get_Context(self):
    ctx = Context(name='Some Name', label='Some label', description='Some description')
    ctx.put()
    found = Context.gql("WHERE name = :1", 'Some Name').fetch(1)[0]
    self.assertEqual('Some label', found.label)

  def test_Update_Context(self):
    ctx = Context(name='Some Name', label='Some label', description='Some description')
    ctx.put()
    found = Context.gql("WHERE name = :1", 'Some Name').fetch(1)[0]
    self.assertEqual('Some label', found.label)
    found.label = 'Some new label'
    found.put()
    self.assertEqual('Some new label', found.label)
    
class Test_CollectionType(framework_Test):
  
  def test_Create_CollectionType(self):
    ct = CollectionType(level=0, name='Some type', description='Some Description')
    ct.put()
    self.assertEqual(1, len(CollectionType.all().fetch(2)))

class Test_Collection(framework_Test):
  
  def test_Create_Collection(self):
    ctx = Context(name='Some Name', label='Some label', description='Some description')
    ctx.put()
    ct = CollectionType(level=0, name='Some type', description='Some Description')
    ct.put()
    collection = Collection(context=ctx, 
                            collection_type=ct,
                            name='COLL1'
                            )
    collection.put()
    self.assertEqual(1, len(CollectionType.all().fetch(2)))
    self.assertEqual('Some Name', 
                     Collection.gql("WHERE name = 'COLL1'").fetch(1)[0].context.name)
    
class Test_CollectionAttributeTemplate(framework_Test):
  
  def test_Create_CollectionAttributeTemplate(self):
    tpl = CollectionAttributeTemplate(name='Some Attribute', label='Attribute',
                                      definition='A block definition', help='help me please')
    tpl.put()
    self.assertEqual(1, len(CollectionAttributeTemplate.all().fetch(1)))

  def test_Create_CollectionAttributeTemplateRank(self):
    tpl = CollectionAttributeTemplate(name='Some Attribute', 
                                      label='Attribute',
                                      definition='A block definition', 
                                      help='help me please', 
                                      rank=1)
    tpl.put()
    self.assertEqual(1, tpl.rank)

    
class Test_CollectionAttribute(framework_Test):
  
  def test_Create_CollectionAttribute(self):
    tpl = CollectionAttributeTemplate(name='Some Attribute', label='Attribute',
                                      definition='A block definition', help='help me please')
    tpl.put()
    ctx = Context(name='Some Name', label='Some label', description='Some description')
    ctx.put()
    ct = CollectionType(level=0, name='Some type', description='Some Description')
    ct.put()
    collection = Collection(context=ctx, 
                            collection_type=ct,
                            name='COLL1'
                            )
    collection.put()    
    user = users.User(email='test@test.com')
    att = CollectionAttribute(collection, attribute=tpl, value='Value', user=user)
    att.put()
    self.assertEqual(1, len(CollectionAttribute.all().fetch(1)))
    self.assertEqual(1, len(collection.attributes))
  
  def test_Create_CollectionAttributeRank(self):
    tpl = CollectionAttributeTemplate(name='Some Attribute', label='Attribute',
                                      definition='A block definition', help='help me please', rank=1)
    tpl.put()
    tpl1 = CollectionAttributeTemplate(name='Some Attribute 1', label='Attribute1',
                                      definition='A block definition 1', help='help me please', rank=2)
    tpl1.put()
    ctx = Context(name='Some Name', label='Some label', description='Some description')
    ctx.put()
    ct = CollectionType(level=0, name='Some type', description='Some Description')
    ct.put()
    collection = Collection(context=ctx, 
                            collection_type=ct,
                            name='COLL1'
                            )
    collection.put()    
    user = users.User(email='test@test.com')
    att = CollectionAttribute(collection, attribute=tpl, value='Value', user=user)
    att.put()
    self.assertEqual(1, len(CollectionAttribute.all().fetch(1)))
    self.assertEqual(1, len(collection.attributes))
    att1 = CollectionAttribute(collection, attribute=tpl, value='Value 1', user=user)
    att1.put()
    self.assertEqual(2, len(collection.attributes))
    self.assertEqual(att, collection.attributes[0])
    
class Test_Variable(framework_Test):
  
  def test_Create_Variable(self):
    self.fail('Init me: %s' % self.__class__.__name__)
  
class Test_Attribute(framework_Test):
  
  def test_Create_Attribute(self):
    self.fail('Init me: %s' % self.__class__.__name__)

class Test_DependentAttribute(framework_Test):
  
  def test_Create_DependentAttribute(self):
    self.fail('Init me: %s' % self.__class__.__name__)

class Test_ReferencedAttribute(framework_Test):
  
  def test_Create_ReferencedAttribute(self):
    self.fail('Init me: %s' % self.__class__.__name__)

class Test_Template(framework_Test):
  
  def test_Create_Template(self):
    self.fail('Init me: %s' % self.__class__.__name__)
  
class Test_TemplateVariable(framework_Test):
  
  def test_Create_TemplateVariable(self):
    self.fail('Init me: %s' % self.__class__.__name__)
  
class Test_UserRole(framework_Test):
  
  def test_Create_UserRole(self):
    self.fail('Init me: %s' % self.__class__.__name__)

class Test_UserPrefs(framework_Test):
  
  def test_Create_UserPrefs(self):
    self.fail('Init me: %s' % self.__class__.__name__)

class Test_Instance(framework_Test):
  
  def test_Create_Instance(self):
    self.fail('Init me: %s' % self.__class__.__name__)
  
  def test_Update_Instance(self):
    self.fail('Init me: %s' % self.__class__.__name__)

class Test_NCI_Controlled_Terminology_Codelist(framework_Test):
  
  
  def test_AddCode(self):
    organisation = Organisation()
    organisation.name='CDISC'
    organisation.put()
    source = Controlled_Terminology_Source(name="SDTM Controlled Terminology",
                                           description = "SDTM Controlled Terminology",
                                           filename="SDTM Controlled Terminology.xls",
                                           organisation = organisation)
    
    source.put()
    ct = NCI_Controlled_Terminology_Codelist(code = 'C12345',
                                             cdisc_submission_value = 'CODED TERM',
                                             cdisc_definition = "Some Definition",
                                             name = 'CODELIST',
                                             extensible = False,
                                             cdisc_synonyms = ['1', '2'],
                                             is_draft = False,
                                             nci_preferred_term = 'Coded term',
                                             source = source)
    ct.put()
    self.assertEqual(1, len(NCI_Controlled_Terminology_Codelist.all().fetch(2)))

  def test_Query(self):
    organisation = Organisation()
    organisation.name='CDISC'
    organisation.put()
    source = Controlled_Terminology_Source(name="SDTM Controlled Terminology",
                                           description = "SDTM Controlled Terminology",
                                           filename="SDTM Controlled Terminology.xls",
                                           organisation = organisation)
    
    source.put()
    # have created the source
    ct = NCI_Controlled_Terminology_Codelist(code = 'C12345',
                                             cdisc_submission_value = 'CODED TERM',
                                             cdisc_definition = "Some Definition",
                                             name = 'CODELIST',
                                             extensible = False,
                                             cdisc_synonyms = ['1', '2'],
                                             is_draft = False,
                                             nci_preferred_term = 'Coded term',
                                             source = source)
    ct.put()
    self.assertEqual(1, len(NCI_Controlled_Terminology_Codelist.all().fetch(2)))
    cl = CodedTerminology.gql("WHERE code = :1", 'C12345').fetch(1)[0]
    self.assertEqual('CDISC', cl.source.organisation.name)

class Test_NCI_Controlled_Terminology_CodelistItem(framework_Test):
  
  
  def test_AddCodeItem(self):
    organisation = Organisation()
    organisation.name='CDISC'
    organisation.put()
    source = Controlled_Terminology_Source(name="SDTM Controlled Terminology",
                                           description = "SDTM Controlled Terminology",
                                           filename="SDTM Controlled Terminology.xls",
                                           organisation = organisation)
    
    source.put()
    ct = NCI_Controlled_Terminology_Codelist(code = 'C12345',
                                             cdisc_submission_value = 'CODED TERM',
                                             cdisc_definition = "Some Definition",
                                             name = 'CODELIST',
                                             extensible = False,
                                             cdisc_synonyms = ['1', '2'],
                                             is_draft = False,
                                             nci_preferred_term = 'Coded term',
                                             source = source)
    ct.put()
    cti = NCI_Controlled_Terminology_CodeListItem(code='C12346',
                                                  cdisc_submission_value = 'CODED ITEM 1',
                                                  cdisc_definition = "Some Definition 1",
                                                  name = 'CODED ITEM 1',
                                                  cdisc_synonyms = ['3', '5'],
                                                  nci_preferred_term = 'Coded item 1'
                                                  )
    cti.codelists.append(ct.key())
    cti.put()
    self.assertEqual(1, len(ct.coded_items))
    ctj = NCI_Controlled_Terminology_CodeListItem(code='C12347',
                                                  cdisc_submission_value = 'CODED ITEM 2',
                                                  cdisc_definition = "Some Definition 2",
                                                  name = 'CODED ITEM 2',
                                                  cdisc_synonyms = ['3'],
                                                  nci_preferred_term = 'Coded item 2')
    ctj.codelists.append(ct.key())
    ctj.put()
    self.assertEqual(2, len(ct.coded_items))
    
  def test_AddCodeItem_to_two_Codelists(self):
    organisation = Organisation()
    organisation.name='CDISC'
    organisation.put()
    source = Controlled_Terminology_Source(name="SDTM Controlled Terminology",
                                           description = "SDTM Controlled Terminology",
                                           filename="SDTM Controlled Terminology.xls",
                                           organisation = organisation)
    
    source.put()
    # create a codelist
    ct = NCI_Controlled_Terminology_Codelist(code = 'C12345',
                                             cdisc_submission_value = 'CODED TERM',
                                             cdisc_definition = "Some Definition",
                                             name = 'CODELIST',
                                             extensible = False,
                                             cdisc_synonyms = ['1', '2'],
                                             is_draft = False,
                                             nci_preferred_term = 'Coded term',
                                             source = source)
    ct.put()
    # create a second codelist
    ct2 = NCI_Controlled_Terminology_Codelist(code = 'C12345',
                                             cdisc_submission_value = 'CODED TERM',
                                             cdisc_definition = "Some Definition",
                                             name = 'CODELIST',
                                             extensible = False,
                                             cdisc_synonyms = ['1', '2'],
                                             is_draft = False,
                                             nci_preferred_term = 'Coded term',
                                             source = source)
    ct2.put()
    # create an item
    cti = NCI_Controlled_Terminology_CodeListItem(code='C12346',
                                                  cdisc_submission_value = 'CODED ITEM 1',
                                                  cdisc_definition = "Some Definition 1",
                                                  cdisc_synonyms = ['3', '5'],
                                                  nci_preferred_term = 'Coded item 1')
    # allocate the item to the two codelists
    cti.codelists.extend([ct.key(), ct2.key()])
    cti.put()
    self.assertEqual(1, len(ct.coded_items))
    self.assertEqual(1, len(ct2.coded_items))
    ctj = NCI_Controlled_Terminology_CodeListItem(code='C12347',
                                                  cdisc_submission_value = 'CODED ITEM 2',
                                                  cdisc_definition = "Some Definition 2",
                                                  cdisc_synonyms = ['3'],
                                                  nci_preferred_term = 'Coded item 2')
    ctj.codelists.append(ct.key())
    ctj.put()
    self.assertEqual(2, len(ct.coded_items))
  
  def test_UpdateCodeItem(self):
    organisation = Organisation()
    organisation.name='CDISC'
    organisation.put()
    source = Controlled_Terminology_Source(name="SDTM Controlled Terminology",
                                           description = "SDTM Controlled Terminology",
                                           filename="SDTM Controlled Terminology.xls",
                                           organisation = organisation)
    
    source.put()
    # create a codelist
    ct = NCI_Controlled_Terminology_Codelist(code = 'C12345',
                                             cdisc_submission_value = 'CODED TERM',
                                             cdisc_definition = "Some Definition",
                                             name = 'CODELIST',
                                             extensible = False,
                                             cdisc_synonyms = ['1', '2'],
                                             is_draft = False,
                                             nci_preferred_term = 'Coded term',
                                             source = source)
    ct.put()
    cti = NCI_Controlled_Terminology_CodeListItem(code='C12346',
                                                  cdisc_submission_value = 'CODED ITEM 1',
                                                  cdisc_definition = "Some Definition 1",
                                                  cdisc_synonyms = ['3', '5'],
                                                  nci_preferred_term = 'Coded item 1'
                                                  )
    cti.codelists.append(ct.key())
    cti.put()
    self.assertEqual('CODED ITEM 1', [x.cdisc_submission_value for x in NCI_Controlled_Terminology_CodeListItem.gql("WHERE code = :1", 'C12346')][0])
    updated_cti = NCI_Controlled_Terminology_CodeListItem.gql("WHERE code = :1", 'C12346').fetch(1)[0]
    updated_cti.cdisc_submission_value = 'CODED ITEM 1.1'
    updated_cti.put()
    self.assertEqual('CODED ITEM 1.1', [x.cdisc_submission_value for x in NCI_Controlled_Terminology_CodeListItem.gql("WHERE code = :1", 'C12346')][0])
    
if __name__ == "__main__":
  unittest.main()
  
